﻿using System;
using System.Collections.Generic;
using System.Text;

public abstract class Vehicle
{
    private Engine m_Engine = null;

    public Engine Engine
    {
        get { return m_Engine; }
        set { m_Engine = value; }
    }

    protected int m_NumOfProperties = 0;
    protected const string k_SetEngineStr = "Please enter the engine type for the vehicle (1. Fuel, 2. Electric):";
    protected const string k_SetModelName = "Please enter the model name of the vehicle:";
    protected const string k_WheelManufacturer = "Please enter the wheel manufacturer of the vehicle's wheels:";

    protected List<VehicleProperty> m_VehicleProperties = null;

    public List<VehicleProperty> VehicleProperties
    {
        get { return m_VehicleProperties; }
    }

    protected string m_ModelName = string.Empty;
    
    public string ModelName
    {
        get { return m_ModelName; }
        set { m_ModelName = value; }
    }

    protected string m_LicenseNumber = string.Empty;

    public string LicenseNumber
    {
        get { return m_LicenseNumber; }
        set { m_LicenseNumber = value; }
    }

    protected float m_EnergyPercentage = 100f;

    public float EnergyPercentage
    {
        get { return m_EnergyPercentage; }
        set { m_EnergyPercentage = value; }
    }

    protected List<Wheel> m_ListOfWheels = null;

    public List<Wheel> ListOfWheels
    {
        get { return m_ListOfWheels; }
        set { m_ListOfWheels = value; }
    }

    protected string m_WheelManufacturer = string.Empty;

    protected string WheelManufacturer
    {
        get { return m_WheelManufacturer; }
        set { m_WheelManufacturer = value; }
    }

    protected void InitilizeWheels(int i_NumOfWheels, Wheel.ePressureType i_WheelPressureType, string i_WheelManufacturerName)
    {
        if (m_ListOfWheels == null)
        {
            m_ListOfWheels = new List<Wheel>();
        }

        for (int i = 0; i < i_NumOfWheels; i++)
        {
            Wheel CurrentWheel = new Wheel(i_WheelManufacturerName, i_WheelPressureType);
            m_ListOfWheels.Add(CurrentWheel);
        } 
    }

    public new Engine.eEngineType GetType
    {
        get
        {
            Engine.eEngineType? result = null;

            if (m_Engine is FuelEngine)
            {
                result = Engine.eEngineType.Fuel;
            }
            else
            {
                result = Engine.eEngineType.Electric;
            }

            return result.Value;
        }
    }

    protected object ValidateEnumRanges(Type i_Type, object i_VehiclePropertyValue)
    {
        int result = 0;
        int.TryParse(i_VehiclePropertyValue.ToString(), out result);
        Array TypeValuesArray = Enum.GetValues(i_Type);
        int MaxValue = (int)TypeValuesArray.GetValue(TypeValuesArray.Length - 1);
        int MinValue = (int)TypeValuesArray.GetValue(0);
        if (result >= MinValue && result <= MaxValue)
        {
            return Enum.Parse(i_Type, i_VehiclePropertyValue.ToString());
        }
        else
        {
            throw new ValueOutOfRangeException("Invalid input", MinValue, MaxValue);
        }
    }

    public void BlowWheel()
    {
        foreach (Wheel CurrentWheel in m_ListOfWheels)
        {
            CurrentWheel.CurrentAirPressure = CurrentWheel.MaxAirPressure;
        }
    }

    protected abstract void AllocateNewEngine(object i_VehiclePropertyValue);

    public abstract void SetVehicleProperty(VehicleProperty i_VehiclePropertyToSet);
    
    protected virtual void AllocateVehicleProperties()
    {
        m_VehicleProperties = new List<VehicleProperty>();

        m_VehicleProperties.Add(new VehicleProperty(k_SetEngineStr, 0, Engine));
        m_VehicleProperties.Add(new VehicleProperty(k_SetModelName, 1, m_ModelName));
        m_VehicleProperties.Add(new VehicleProperty(k_WheelManufacturer, 2, m_WheelManufacturer));
    }

    public new virtual string ToString()
    {
        string str = string.Concat("License Number: ", m_LicenseNumber, System.Environment.NewLine, "Model Name: ", m_ModelName, System.Environment.NewLine);

        str = string.Concat(str, m_Engine.ToString());
        str = string.Concat(str, "There are ", m_ListOfWheels.Count, " wheels", System.Environment.NewLine, m_ListOfWheels[0].ToString());
        
        return str;
    }
}
